﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Configuration;
using Esint.Common.Model;
using System.Data;
using System.Reflection;

namespace Esint.Common
{
    public class CommonExtend
    {
        private static object m_Lock = new object();//读写文件锁，用来解决多线程写日志冲突的问题
        static readonly string strLogDir = AppDomain.CurrentDomain.BaseDirectory + "Log\\";
        
        /// <summary>
        /// 记录错误日志方法
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="selfDefinedInfo"></param>
        public static void ErrorLog(Exception ex, string selfDefinedInfo)
        {
            if (!Directory.Exists(strLogDir))
            {
                Directory.CreateDirectory(strLogDir);//不存在目录，创建目录
            }

            string logPath = strLogDir + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";

            string str_info = string.Format("-----------------------start-------------------------" + Environment.NewLine
                + "【发生时间】：{0}" + Environment.NewLine
                + "【错误信息】：{1}" + Environment.NewLine
                + "【自定义信息】：{2}" + Environment.NewLine
                + "【堆栈信息】：{3}" + Environment.NewLine
                + "-----------------------end-------------------------" + Environment.NewLine
                , DateTime.Now.ToString(), ex.Message, selfDefinedInfo, ex.StackTrace);

            lock (m_Lock)
            {
                File.AppendAllText(logPath, str_info);
            }
        }

        /// <summary>
        /// 下载通用方法
        /// </summary>
        /// <param name="context"></param>
        /// <param name="FilePathToWebRoot"></param>
        /// <param name="DisplayName"></param>
        public static void DownloadFile(HttpContext context, string FilePathToWebRoot, string DisplayName)
        {
            string fileName = DisplayName;//客户端保存的文件名
            string filePath = context.Server.MapPath(FilePathToWebRoot);//路径

            //以字符流的形式下载文件
            FileStream fs = new FileStream(filePath, FileMode.Open);
            byte[] bytes = new byte[(int)fs.Length];
            fs.Read(bytes, 0, bytes.Length);
            fs.Close();
            context.Response.ContentType = "application/octet-stream";
            //通知浏览器下载文件而不是打开
            context.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
            context.Response.AddHeader("Content-Transfer-Encoding", "binary");
            context.Response.ContentType = "application/octet-stream;charset=utf-8";
            context.Response.BinaryWrite(bytes);
            context.Response.Flush();
            context.Response.End();
        }

        /// <summary>
        /// 计算当前是第几周
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int GetWeekOfYear(DateTime dt) { GregorianCalendar gc = new GregorianCalendar(); return gc.GetWeekOfYear(dt, CalendarWeekRule.FirstDay, DayOfWeek.Monday); }
        
        /// <summary>
        /// 将对象转换为JSON串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ConvertTJson(Object obj)
        {
            string JsonStr = JsonConvert.SerializeObject(obj, Formatting.None);
            JsonStr = JsonStr.Replace(":null,", ":\"\",");
            return JsonStr;
        }

        /// <summary>
        /// 使用sha1加密字符串
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string GetSha1String(string text)
        {
            var sha1 = new SHA1CryptoServiceProvider();
            byte[] str01 = Encoding.Default.GetBytes(text);
            byte[] str02 = sha1.ComputeHash(str01);
            var result = BitConverter.ToString(str02).Replace("-", "");
            return result;
        }

        /// <summary>
        /// MD5字符串加密
        /// </summary>
        /// <param name="txt"></param>
        /// <returns>加密后字符串</returns>
        public static string GetMD5String(string txt)
        {
            using (MD5 mi = MD5.Create())
            {
                byte[] buffer = Encoding.Default.GetBytes(txt);
                //开始加密
                byte[] newBuffer = mi.ComputeHash(buffer);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < newBuffer.Length; i++)
                {
                    sb.Append(newBuffer[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }

        /// <summary>
        /// 发送Http Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static string HttpPost(string url, Dictionary<string, string> dic)
        {
            string result = string.Empty;
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Timeout = 1000 * 60 * 60;
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            #region 添加Post 参数
            StringBuilder builder = new StringBuilder();
            int i = 0;
            foreach (var item in dic)
            {
                if (i > 0)
                    builder.Append("&");
                builder.AppendFormat("{0}={1}", item.Key, item.Value);
                i++;
            }
            byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
            req.ContentLength = data.Length;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            #endregion
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

            Stream stream = resp.GetResponseStream();
            //获取响应内容
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }
            return result;
        }

        /// <summary>
        /// 发送Http Get请求
        /// </summary>
        /// <param name="URL"></param>
        /// <returns></returns>
        public static string HttpGet(string URL, string MoreInfo, Encoding encoding)
        {
            Debug.WriteLine($"GET请求：{URL}");
            string result = string.Empty;
            try
            {
                Thread.Sleep(100);
                HttpWebRequest wbRequest = (HttpWebRequest)WebRequest.Create(URL);
                wbRequest.Method = "GET";
                wbRequest.KeepAlive = false;
                wbRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0";
                CookieContainer cookieContainer = new CookieContainer();
                wbRequest.CookieContainer = cookieContainer;
                HttpWebResponse wbResponse = (HttpWebResponse)wbRequest.GetResponse();
                using (Stream responseStream = wbResponse.GetResponseStream())
                {
                    using (StreamReader sReader = new StreamReader(responseStream, encoding))
                    {
                        result = sReader.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorLog(ex, $"传入的URL为{URL}||{MoreInfo}");
                throw ex;
            }
            return result;
        }

        ///<summary>
        ///恢复html中的特殊字符
        ///</summary>
        ///<paramname="theString">需要恢复的文本。</param>
        ///<returns>恢复好的文本。</returns>
        public static string HtmlDecode(string theString)
        {
            theString = HttpUtility.HtmlDecode(theString);

            //theString = theString.Replace("&gt;", ">");
            //theString = theString.Replace("&lt;", "<");
            //theString = theString.Replace("&nbsp;", string.Empty);
            theString = theString.Replace("&nbsp", string.Empty);
            //theString = theString.Replace("&quot;", "\"");
            //theString = theString.Replace("&quot;", "\"");
            //theString = theString.Replace("&#39;", "\'");
            //theString = theString.Replace("<br/>", "\n");
            theString = theString.Replace("\r", string.Empty);
            theString = theString.Replace("\n", string.Empty);
            theString = theString.Replace("\t", string.Empty);
            theString = theString.Replace(" ", string.Empty);
            theString = Regex.Replace(theString, "\u3000", string.Empty);
            theString = Regex.Replace(theString, "\u00A0", string.Empty);
            return theString;
        }

        /// <summary>
        /// 自定义比较字符串方法
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public static bool CompareStr(string str1, string str2)
        {
            if (str1.Length != str2.Length)
            {
                return false;
            }

            bool IsSame = true;
            for (int i = 0; i < str1.Length; i++)
            {
                if (str1[i] != str2[i])
                {
                    if ((str1[i] >= 0x4e00 && str1[i] <= 0x9fbb) && (str2[i] >= 0x4e00 && str2[i] <= 0x9fbb) //两个字符都是汉字
                        || (char.IsLetter(str1[i]) && char.IsLetter(str2[i])) //两个字符都是字母
                        || (char.IsNumber(str1[i]) && char.IsNumber(str2[i])) //两个字符都是数字
                        )
                    {
                        IsSame = false;
                        break;
                    }
                }
            }

            return IsSame;
        }

        /// <summary>
        /// 检查文件名中是否包含非法字符,如 \ / : * ? " < > | 
        /// </summary>
        /// <param name="fileName">待处理的文件名</param>
        /// <returns>处理后的文件名</returns>
        public static bool CheckFileName(string fileName)
        {
            bool Isllegal = true;
            List<char> illegalList = new List<char>()
            {
                '\\',
                '/',
                ':',
                '*',
                '?',
                '"',
                '<',
                '>',
                '|',
                ' ',
                '\'',
            };

            string str = fileName;
            foreach (var c in str)
            {
                if(illegalList.Contains(c))
                {
                    Isllegal = false;
                }
            }

            return Isllegal;
        }

        /// <summary>
        /// 读取配置文件的AppSettings方法
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetAppSetting(string key)
        {
            string configContent = ConfigurationManager.AppSettings[key];
            return configContent;
        }

        /// <summary>
        /// 获得类型上的特性方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T GetAttributeObject<T>(Type t) where T: Attribute
        {
            T myattribute = Attribute.GetCustomAttribute(t, typeof(T)) as T;
            return myattribute;
        }

        /// <summary>
        /// 自定义随机数方法
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static int CustomRandom(int min, int max)
        {
            int GetRandomSeed()
            {
                byte[] bytes = new byte[4];
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                rng.GetBytes(bytes);
                return BitConverter.ToInt32(bytes, 0);
            }

            int GetRandomSeed2()
            {
                long tick = DateTime.Now.Ticks;
                return ((int)(tick & 0xffffffffL) | (int)(tick >> 32));
            }
            
            var seed = GetRandomSeed() + GetRandomSeed2();

            return new Random(seed).Next(min, max);
        }

        /// <summary>
        /// 日期转星期几方法
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string GetDayOfWeekChinese(DateTime time)
        {
            string str = string.Empty;
            switch (time.DayOfWeek)
            {
                default:
                    break;
                case  DayOfWeek.Monday:
                    {
                        str = "星期一";
                        break;
                    }

                case DayOfWeek.Tuesday:
                    {
                        str = "星期二";
                        break;
                    }

                case DayOfWeek.Wednesday:
                    {
                        str = "星期三";
                        break;
                    }

                case DayOfWeek.Thursday:
                    {
                        str = "星期四";
                        break;
                    }

                case DayOfWeek.Friday:
                    {
                        str = "星期五";
                        break;
                    }

                case DayOfWeek.Saturday:
                    {
                        str = "星期六";
                        break;
                    }

                case DayOfWeek.Sunday:
                    {
                        str = "星期日";
                        break;
                    }
            }

            return str;
        }

        /// <summary>
        /// 日期转星期几方法
        /// </summary>
        /// <param name="timeStr"></param>
        /// <returns></returns>
        public static string GetDayOfWeekChinese(string timeStr)
        {
            DateTime time = Convert.ToDateTime(timeStr);

            return GetDayOfWeekChinese(time);
        }
    }
}